﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using DataBase;
using DBService;
using YArchitech.Revit.MEP.Opening.Common;

namespace YArchitech.Revit.MEP.Opening
{
	public class DbFloorToBeOpened : DbOpeningBase, IDbObject
	{
		public DbFloorToBeOpened(int projectId, XYZ basePt, int floorId, int pipeId, SectionParameter sp, BoxParameter bp, CutType cType, HostType hType, string level)
		{
			this.mGuid = Guid.NewGuid();
			this.mProjectId = projectId;
			this.mHostId = floorId;
			this.mPt = basePt;
			this.mParameter = sp;
			base.BoxParameter = bp;
			base.CutType = cType;
			base.HostType = hType;
			base.Level = level;
			base.Date = DateTime.Now;
			base.IsCurrentProject = true;
			this.mPipeId = pipeId;
		}

		public override bool Equals(object obj)
		{
			if (obj is DbFloorToBeOpened)
			{
				DbFloorToBeOpened dbFloorToBeOpened = (DbFloorToBeOpened)obj;
				return dbFloorToBeOpened.mPt.IsAlmostEqualTo(this.mPt) && dbFloorToBeOpened.HostId == base.HostId;
			}
			return false;
		}

		public override void WirteToXML(string fileName)
		{
			XmlUtils.AddFloorOpening(fileName, this);
		}

		public static List<DbFloorToBeOpened> ReadFromXML(string fileName)
		{
			return XmlUtils.ReadFloorOpening(fileName);
		}

		public static DbFloorToBeOpened ReadFromXML(Guid id, string fileName)
		{
			return XmlUtils.ReadFloorOpening(id, fileName);
		}

		public override void UpdateToXML(string fileName)
		{
			XmlUtils.UpdateFloorOpeningToXML(fileName, this);
		}

		public static List<DbFloorToBeOpened> GetByProject(DbProject project)
		{
			List<DbFloorToBeOpened> result;
			try
			{
				if (project.Database.Connection.State == ConnectionState.Closed)
				{
					project.Database.Connection.Open();
				}
				List<DbFloorToBeOpened> list = new List<DbFloorToBeOpened>();
				string sql = string.Format("SELECT ProjectId,HostId,PtX,PtY,PtZ,Parameter1,Parameter2,SectionType,Guid,Status,BoxParameter1,BoxParameter2,BoxParameter3,BoxParameter4,Level,CutType,HostType,BoxSectionType,Remark,PipeId FROM tbSynergyOpiening WHERE ProjectId={0} and HostType=1", project.Id);
				DataTable dataTable = project.Database.ExecQuery(sql);
				if (project.Database.Connection.State == ConnectionState.Open)
				{
					project.Database.Connection.Close();
				}
				if (dataTable == null)
				{
					result = null;
				}
				else
				{
					for (int i = 0; i < dataTable.Rows.Count; i++)
					{
						int projectId = Convert.ToInt32(dataTable.Rows[i]["ProjectId"]);
						Guid guid = Guid.Parse(dataTable.Rows[i]["Guid"].ToString());
						int floorId = Convert.ToInt32(dataTable.Rows[i]["HostId"]);
						int pipeId = Convert.ToInt32(dataTable.Rows[i]["PipeId"]);
						OpeningStatus status = (OpeningStatus)dataTable.Rows[i]["Status"];
						XYZ basePt = new XYZ(Convert.ToDouble(dataTable.Rows[i]["PtX"]), Convert.ToDouble(dataTable.Rows[i]["PtY"]), Convert.ToDouble(dataTable.Rows[i]["PtZ"]));
						DBService.SectionType sectionType = (DBService.SectionType)Convert.ToInt32(dataTable.Rows[i]["SectionType"]);
						SectionParameter sp = null;
						if (sectionType == DBService.SectionType.Arc)
						{
							sp = new SectionParameter(Convert.ToDouble(dataTable.Rows[i]["Parameter1"]));
						}
						else if (sectionType == DBService.SectionType.Rect)
						{
							double param = Convert.ToDouble(dataTable.Rows[i]["Parameter1"]);
							double param2 = Convert.ToDouble(dataTable.Rows[i]["Parameter2"]);
							sp = new SectionParameter(param, param2);
						}
						DBService.SectionType sectionType2 = (DBService.SectionType)Convert.ToInt32(dataTable.Rows[i]["BoxSectionType"]);
						BoxParameter bp = null;
						if (sectionType2 == DBService.SectionType.Arc)
						{
							bp = new BoxParameter(Convert.ToDouble(dataTable.Rows[i]["BoxParameter1"]));
						}
						else if (sectionType2 == DBService.SectionType.Rect)
						{
							double param3 = Convert.ToDouble(dataTable.Rows[i]["BoxParameter1"]);
							double param4 = Convert.ToDouble(dataTable.Rows[i]["BoxParameter1"]);
							double param5 = Convert.ToDouble(dataTable.Rows[i]["BoxParameter3"]);
							double param6 = Convert.ToDouble(dataTable.Rows[i]["BoxParameter4"]);
							bp = new BoxParameter(param3, param4, param5, param6);
						}
						CutType cType = (CutType)Convert.ToInt32(dataTable.Rows[i]["CutType"]);
						HostType hType = (HostType)Convert.ToInt32(dataTable.Rows[i]["HostType"]);
						string level = Convert.ToString(dataTable.Rows[i]["Level"]);
						string remark = Convert.ToString(dataTable.Rows[i]["Remark"]);
						list.Add(new DbFloorToBeOpened(projectId, basePt, floorId, pipeId, sp, bp, cType, hType, level)
						{
							Remark = remark,
							Guid = guid,
							mDatabase = project.Database,
							Status = status
						});
					}
					result = list;
				}
			}
			catch (Exception ex)
			{
				if (project.Database.Connection.State == ConnectionState.Open)
				{
					project.Database.Connection.Close();
				}
				throw ex;
			}
			return result;
		}

		private FamilySymbol LoadFitOpeningSymbol(Autodesk.Revit.DB.Document doc, string version)
		{
			string strFamilyName = "";
			if (base.OpeningParameter.SectionType == DBService.SectionType.Arc)
			{
				strFamilyName = "楼板洞口-圆形";
			}
			else if (base.OpeningParameter.SectionType == DBService.SectionType.Rect)
			{
				strFamilyName = "楼板洞口-矩形";
			}
			return DbOpeningBase.LoadOpeningFamily(doc, strFamilyName);
		}

		public override void AddOpeningTag(UIApplication uiApp, TagStyle ts)
		{
			Document document = uiApp.ActiveUIDocument.Document;
			XYZ basisZ = XYZ.BasisZ;
			XYZ xyz = RevitVersionFuncs.CreateRotationAtPoint(basisZ, base.PipeConnAxisXOnSectionPlaneAng, basisZ).OfVector(XYZ.BasisX);
			XYZ baseY = basisZ.CrossProduct(xyz).Normalize();
			double num = AssistFunc.mmToFeet(50.0);
            //base.Location + basisZ * num;
			Plane plane = RevitVersionFuncs.CreatePlanByOriginAndBasis(base.Location, xyz, baseY);
            //XYZ.BasisZ * num;
			List<ModelCurve> list = new List<ModelCurve>();
			if (base.SectionParameter.SectionType == DBService.SectionType.Rect)
			{
				double dHalfW = AssistFunc.mmToFeet(base.SectionParameter.Parameter2 * 0.5 + base.BoxParameter.Parameter1);
				double dHalfH = AssistFunc.mmToFeet(base.SectionParameter.Parameter1 * 0.5 + base.BoxParameter.Parameter1);
				Transaction transaction = new Transaction(document, "CreateSketchPlane");
				transaction.Start();
				try
				{
					SketchPlane sketchPlane = RevitVersionFuncs.NewSketchPlane(document, plane);
					transaction.Commit();
					list = base.CreateRectOpeningCvs(document, base.Guid.ToString(), dHalfW, dHalfH, sketchPlane);
					goto IL_1B7;
				}
				catch
				{
					transaction.RollBack();
					goto IL_1B7;
				}
			}
			double dR = AssistFunc.mmToFeet(base.SectionParameter.Parameter1 * 0.5 + base.BoxParameter.Parameter1);
			Transaction transaction2 = new Transaction(document, "CreateSketchPlane");
			transaction2.Start();
			try
			{
				SketchPlane sketchPlane2 = RevitVersionFuncs.NewSketchPlane(document, plane);
				transaction2.Commit();
				list = base.CreateCircleOpeningCvs(document, base.Guid.ToString(), dR, sketchPlane2);
			}
			catch
			{
				transaction2.RollBack();
			}
			IL_1B7:
			ElementSet elementSet = new ElementSet();
			foreach (ModelCurve modelCurve in list)
			{
				elementSet.Insert(modelCurve);
			}
			if (elementSet.Size > 0)
			{
				Transaction transaction3 = new Transaction(document, "CreateGroup");
				transaction3.Start();
				try
				{
					RevitVersionFuncs.NewGroup(document, elementSet).GroupType.Name = "协同开洞标记_" + base.Guid.ToString();
					transaction3.Commit();
				}
				catch
				{
					transaction3.RollBack();
				}
			}
		}

		public override Element Create(UIApplication uiApp)
		{
			Document document = uiApp.ActiveUIDocument.Document;
			FilledRegion elem = this.CreateFloorOpening2D(document);
			try
			{
				Floor floor = RevitVersionFuncs.GetElement(document, new ElementId(this.mHostId)) as Floor;
				FamilySymbol familySymbol = this.LoadFitOpeningSymbol(document, document.Application.VersionNumber);
				string text = this.FormatFloorOpeningFamilyName();
				Family family = ElementFiltering.FindFamily(document, text);
				FamilySymbol familySymbol2;
				if (family == null)
				{
					familySymbol2 = CmdTools.CreateFamilySymbolByTemplate(familySymbol.Family, text, this);
				}
				else
				{
					familySymbol2 = family.GetSymbols().FirstOrDefault<FamilySymbol>();
				}
				FamilyInstance familyInstance = null;
				if (familySymbol2 != null)
				{
					Transaction transaction = new Transaction(document, "CreateOpening");
					transaction.Start();
					try
					{
						UnifiedModified.ActivateFamilySymbol(familySymbol2);
						familyInstance = document.Create.NewFamilyInstance(base.Location, familySymbol2, floor, (Autodesk.Revit.DB.Structure.StructuralType)0);
						transaction.Commit();
					}
					catch
					{
						transaction.RollBack();
					}
				}
				if (familyInstance != null)
				{
					Transaction transaction2 = new Transaction(document, "ModifyFi");
					transaction2.Start();
					try
					{
						string paramName = (base.SectionParameter.SectionType == DBService.SectionType.Arc) ? "洞口直径" : "洞口高度";
						double num = AssistFunc.mmToFeet(base.SectionParameter.Parameter1 + base.BoxParameter.Parameter1);
						familyInstance.GetParameter(paramName).Set(num + AssistFunc.mmToFeet(0.01));
						transaction2.Commit();
					}
					catch
					{
						transaction2.RollBack();
					}
				}
				base.Status = OpeningStatus.Opened;
				base.SetDate(familyInstance);
				CmdTools.WriteToElement(elem, DbOpeningBase.guidOpening3D, familyInstance.Id.IntegerValue);
				this.AddSharedParameter(familyInstance);
				base.OpeningID = familyInstance.Id;
				return familyInstance;
			}
			catch
			{
			}
			return null;
		}

		private FilledRegion CreateFloorOpening2D(Autodesk.Revit.DB.Document doc)
		{
			try
			{
				XYZ xyz = Transform.CreateRotationAtPoint(XYZ.BasisZ, base.PipeConnAxisXOnSectionPlaneAng, base.Location).OfVector(XYZ.BasisX).Normalize();
				XYZ xyz2 = XYZ.BasisZ.CrossProduct(xyz).Normalize();
				List<CurveLoop> list = new List<CurveLoop>();
				CurveLoop curveLoop = new CurveLoop();
				if (base.SectionParameter.SectionType == DBService.SectionType.Arc)
				{
					double num = AssistFunc.mmToFeet(base.SectionParameter.Parameter1 * 0.5 + base.BoxParameter.Parameter1);
					XYZ xyz3 = base.Location - xyz * num;
					XYZ xyz4 = base.Location + xyz * num;
					XYZ xyz5 = base.Location + xyz2 * num;
					XYZ xyz6 = base.Location - xyz2 * num;
					Arc arc = Arc.Create(xyz3, xyz4, xyz5);
					Arc arc2 = Arc.Create(xyz4, xyz3, xyz6);
					curveLoop.Append(arc);
					curveLoop.Append(arc2);
					list.Add(curveLoop);
				}
				else
				{
					double num2 = AssistFunc.mmToFeet(base.SectionParameter.Parameter2 * 0.5 + base.BoxParameter.Parameter1);
					double num3 = AssistFunc.mmToFeet(base.SectionParameter.Parameter1 * 0.5 + base.BoxParameter.Parameter1);
					XYZ xyz7 = base.Location - xyz * num2;
					xyz7 += xyz2 * num3;
					XYZ xyz8 = xyz7 - xyz2 * num3 * 2.0;
					XYZ xyz9 = xyz8 + xyz * num2 * 2.0;
					XYZ xyz10 = xyz7 + xyz * num2 * 2.0;
					curveLoop.Append(Line.CreateBound(xyz7, xyz8));
					curveLoop.Append(Line.CreateBound(xyz8, xyz9));
					curveLoop.Append(Line.CreateBound(xyz9, xyz10));
					curveLoop.Append(Line.CreateBound(xyz10, xyz7));
					list.Add(curveLoop);
				}
				Transaction transaction = new Transaction(doc, "CreateFilledRegion");
				transaction.Start();
				try
				{
					FilledRegion filledRegion = null;
					ViewPlan viewPlanByName = base.GetViewPlanByName(doc);
					if (viewPlanByName != null)
					{
						filledRegion = FilledRegion.Create(doc, CmdCreateOpening.m_filledRegionType.Id, viewPlanByName.Id, list);
						filledRegion.SetLineStyleId(CmdCreateOpening.m_lineStyleOpening2D.Id);
						viewPlanByName.SetYJKProjLinePatternOverrideByElement(new List<ElementId>
						{
							filledRegion.Id
						}, CmdCreateOpening.m_linePattern);
					}
					transaction.Commit();
					return filledRegion;
				}
				catch
				{
					transaction.RollBack();
				}
			}
			catch
			{
			}
			return null;
		}

		private void AddSharedParameter(Element elem)
		{
			Document document = elem.Document;
			Transaction transaction = new Transaction(document, "AddSharedParameter");
			try
			{
				transaction.Start();
				List<string> list = new List<string>();
				list.Add(DbOpeningBase.m_strSharedParaOpeningMajor);
				list.Add(DbOpeningBase.m_strSharedParaOpeningSize);
                BuiltInCategory integerValue = (BuiltInCategory)elem.Category.Id.IntegerValue;
				Dictionary<string, ParameterType> dictionary = new Dictionary<string, ParameterType>();
				foreach (string text in list)
				{
					if (elem.GetParameter(text) == null)
					{
                        dictionary.Add(text, (ParameterType)1);
					}
				}
				if (dictionary.Count > 0)
				{
					SharedParameter.InsertSharedParameter(document, integerValue, "洞口信息", dictionary, false, true);
				}
				Parameter parameter = elem.GetParameter(DbOpeningBase.m_strSharedParaOpeningMajor);
				if (parameter != null)
				{
					parameter.Set(base.MajorString);
				}
				parameter = elem.GetParameter(DbOpeningBase.m_strSharedParaOpeningSize);
				if (parameter != null)
				{
					string text2;
					if (base.SectionParameter.SectionType == DBService.SectionType.Arc)
					{
						text2 = "φ" + (base.SectionParameter.Parameter1 + base.BoxParameter.Parameter1 * 2.0).ToString("F0");
					}
					else
					{
						double num = base.SectionParameter.Parameter1 + base.BoxParameter.Parameter1 * 2.0;
						text2 = (base.SectionParameter.Parameter2 + base.BoxParameter.Parameter1 * 2.0).ToString("F0") + "X" + num.ToString("F0");
					}
					parameter.Set(text2);
				}
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
		}

		private string FormatFloorOpeningFamilyName()
		{
			try
			{
				string result = "圆形楼板洞";
				if (base.SectionParameter.SectionType == DBService.SectionType.Rect)
				{
					double num = CmdTools.R2A(base.PipeConnAxisXOnSectionPlaneAng);
					double num2 = base.SectionParameter.Parameter2 + base.BoxParameter.Parameter1;
					double num3 = base.SectionParameter.Parameter1 + base.BoxParameter.Parameter1;
					result = string.Format("矩形楼板洞_Ang{0:F2}_W{1:F2}_H{2:F2}", num, num2, num3);
				}
				return result;
			}
			catch
			{
			}
			return "";
		}

		public static DbFloorToBeOpened GetFromDB(Guid id, BimServerDB db)
		{
			DbFloorToBeOpened result;
			try
			{
				if (db.Connection.State == ConnectionState.Closed)
				{
					db.Connection.Open();
				}
				DbCommand dbCommand = db.Connection.CreateCommand();
				dbCommand.CommandText = string.Format("SELECT ProjectId,HostId,PtX,PtY,PtZ,Parameter1,Parameter2,SectionType,Id,Status,BoxParameter1,BoxParameter2,BoxParameter3,BoxParameter4,Level,CutType,HostType,BoxSectionType,Remark,PipeId FROM tbSynergyOpiening WHERE Guid={0} and HostType=1", "@id");
				SqlParameter sqlParameter = new SqlParameter("@id", SqlDbType.UniqueIdentifier);
				sqlParameter.Value = id;
				dbCommand.Parameters.Add(sqlParameter);
				IDataReader dataReader = dbCommand.ExecuteReader();
				DataTable dataTable = db.DataReaderToDataTable(dataReader);
				dataReader.Dispose();
				if (db.Connection.State == ConnectionState.Open)
				{
					db.Connection.Close();
				}
				if (dataTable == null)
				{
					result = null;
				}
				else
				{
					int projectId = Convert.ToInt32(dataTable.Rows[0]["ProjectId"]);
					int floorId = Convert.ToInt32(dataTable.Rows[0]["HostId"]);
					int pipeId = Convert.ToInt32(dataTable.Rows[0]["PipeId"]);
					OpeningStatus status = (OpeningStatus)dataTable.Rows[0]["Status"];
					XYZ basePt = new XYZ(Convert.ToDouble(dataTable.Rows[0]["PtX"]), Convert.ToDouble(dataTable.Rows[0]["PtY"]), Convert.ToDouble(dataTable.Rows[0]["PtZ"]));
					DBService.SectionType sectionType = (DBService.SectionType)Convert.ToInt32(dataTable.Rows[0]["SectionType"]);
					SectionParameter sp = null;
					if (sectionType == DBService.SectionType.Arc)
					{
						sp = new SectionParameter(Convert.ToDouble(dataTable.Rows[0]["Parameter1"]));
					}
					else if (sectionType == DBService.SectionType.Rect)
					{
						double param = Convert.ToDouble(dataTable.Rows[0]["Parameter1"]);
						double param2 = Convert.ToDouble(dataTable.Rows[0]["Parameter2"]);
						sp = new SectionParameter(param, param2);
					}
					DBService.SectionType sectionType2 = (DBService.SectionType)Convert.ToInt32(dataTable.Rows[0]["BoxSectionType"]);
					BoxParameter bp = null;
					if (sectionType2 == DBService.SectionType.Arc)
					{
						bp = new BoxParameter(Convert.ToDouble(dataTable.Rows[0]["BoxParameter1"]));
					}
					else if (sectionType2 == DBService.SectionType.Rect)
					{
						double param3 = Convert.ToDouble(dataTable.Rows[0]["BoxParameter1"]);
						double param4 = Convert.ToDouble(dataTable.Rows[0]["BoxParameter1"]);
						double param5 = Convert.ToDouble(dataTable.Rows[0]["BoxParameter3"]);
						double param6 = Convert.ToDouble(dataTable.Rows[0]["BoxParameter4"]);
						bp = new BoxParameter(param3, param4, param5, param6);
					}
					CutType cType = (CutType)Convert.ToInt32(dataTable.Rows[0]["CutType"]);
					HostType hType = (HostType)Convert.ToInt32(dataTable.Rows[0]["HostType"]);
					string level = Convert.ToString(dataTable.Rows[0]["Level"]);
					string remark = Convert.ToString(dataTable.Rows[0]["Remark"]);
					result = new DbFloorToBeOpened(projectId, basePt, floorId, pipeId, sp, bp, cType, hType, level)
					{
						Remark = remark,
						mGuid = id,
						mDatabase = db,
						Status = status
					};
				}
			}
			catch (Exception ex)
			{
				if (db.Connection.State == ConnectionState.Open)
				{
					db.Connection.Close();
				}
				throw ex;
			}
			return result;
		}
	}
}
